/**
 ******************************************************************************
 * @file	watch_opm.c
 * @brief	在串口终端上提供的光功率计界面

- 2017-6-23,MenglongWu,MenglongWoo@aliyun.com
 *
Copyright (C) 2017 桂林聚联科技有限公司, Inc. All Rights Reserved.
*/


#include <stdio.h>
#include <string.h>
#include <prj_type.h>
#include <TR700Driver.h>
#include <project.h>
#include "printl.h"
#include <math.h>
#include <unos_input.h>
#include <cui.h>

#define LASE_WAVE_COUNT (5)  // 1310 1550 1625 1490 850



struct _watch_opm_private {
	int             *isdebug;
	unsigned short  *adc;
	float           *dbm;
	unsigned int    *mode;
	int    *lv;
	int    *wave;
};


/*
   ADC:1108  (-65.15dBm)  <1k>  |  Auto  LV <1>
                  -         -      ^         ^-
*/
#define COUNT_CONTROL (3)
static void _draw(unsigned int select, void *v)
{
	struct _watch_opm_private *p  = (struct _watch_opm_private *)v;
	char *c_item[COUNT_CONTROL]  = {C_NORMAL, C_NORMAL, C_NORMAL};
	char *pstrdebug[]            = {"Auto", "Debug"};
	char *strmode[]              = {"cw", "270", "1k", "2k"};  // TODO off
	char *strwave[]              = {"1310",  "1550", "1625", "1490", "850"};
	char *pdebug;
	char *pmode;
	char *pwave;


	c_item[select % ARRAY_SIZE(c_item)] = (C_CYAN AC_REVERSE);  // 高亮选中列
	
	// TODO sizeof(*pstrdebug)永远是4，正确写法是 sizeof(pstrdebug)
	pdebug = pstrdebug[*(p->isdebug) % sizeof(*pstrdebug)];
	pmode    = strmode[*(p->mode)    % sizeof(*strmode)];
	// pwave    = strwave[*(p->wave)    % sizeof(*strwave)];
	pwave    = strwave[(unsigned int)*(p->wave)    % 5];  // 上面的写法又错误


	printf("ADC:%4d  "
	       "(%6.2fdBm)  "
	       "<%s>  "
	       "|  "
	       "%s%6s   "C_NORMAL
	       "LV %s<%d> " C_NORMAL
	       "%s%snm\r" C_NORMAL,
	       *(p->adc),
	       *(p->dbm),
	       pmode,
	       c_item[0], pdebug,
	       c_item[1], *(p->lv),
	       c_item[2], pwave);
}

static void _key_process(unsigned int *select, void *v, int key)
{
	struct _watch_opm_private *p = (struct _watch_opm_private *)v;
	int deta = 1;

	switch (key) {
	case VK_DOWN:
	case 's':
		deta      = -deta;
	case VK_UP:
	case 'w':
		switch( (unsigned int)(*select) % COUNT_CONTROL ) {
		case 0:  // auto/debug
			*(p->isdebug) = !*(p->isdebug);
			break;
		case 1:  // lv
			if (*(p->isdebug)) {
				*(p->lv) += deta;
				if (*(p->lv) > 7) {
					*(p->lv) = 1;
				} else if (*(p->lv) < 1) {
					*(p->lv) = 7;
				}
			}
			break;
		case 2:
			*(p->wave) += deta;
			*(p->wave) %= LASE_WAVE_COUNT;
			break;
		default:
			break;
		}
		break;
	case VK_RIGHT:
	case 'd':
		(*select)++;
		break;
	case VK_LEFT:
	case 'a':
		(*select)--;
		break;
	default:
		break;
	}
}


#define TASK_DETA_READKEY   (20 * _1MS)
#define TASK_DETA_AUTO_OPM  (500 * _1MS)


void watch_opm()
{
	// 多少都无所谓，只不过如果设置为0
	unsigned int  select = 1000 * COUNT_CONTROL;
	int           key = 0;
	unsigned long task_readkey;
	unsigned long task_auto_opm;


	int                 isdebug = 0;
	unsigned short      adc     = 0;
	float               dbm     = 0;
	unsigned int        mode    = 0;
	int                 lv      = 0;
	int                 wave    = CTRL_OPM_WAVE_1310 + LASE_WAVE_COUNT * 1000;
	struct _watch_opm_private draw;

	draw.isdebug = &isdebug;
	draw.adc     = &adc;
	draw.dbm     = &dbm;
	draw.mode    = &mode;
	draw.lv      = &lv;
	draw.wave    = &wave;

	printf(C_CYAN
	       "[q]:Quit  ['w'/up , 's'/down]:Edit  "
	       "['a'/left , 's'/right']:move cursor \r\n"
	       C_NORMAL);
	task_readkey  = jiffies + TASK_DETA_READKEY;
	task_auto_opm = jiffies + TASK_DETA_AUTO_OPM;
	while(key != 'q') {
		key = 0;
		if (time_after(jiffies, task_readkey)) {
			task_readkey    = jiffies + TASK_DETA_READKEY;
			key = getkeycode();
			if (key > 0) {
				_key_process(&select, &draw, key);
				_draw(select, &draw);
				Ctrl_OPM_SW(lv);
				Ctrl_OPMWave(wave);
			}
		}

		if (time_after(jiffies, task_auto_opm)) {
			task_auto_opm = jiffies + TASK_DETA_AUTO_OPM;
			if (isdebug == 0) {
				AutoCtrl_OPM();
			}
			adc = GetAD(AD_CH_OPM);
			dbm = AutoADC2dBm();
			lv  = Get_OPM_SW();
			// printf("wave %d...\r\n", *(draw.wave) );
			_draw(select, &draw);
		}
	}
	printf("\r\n");
}

